#include "BaseType.h"
#include "Tracer.h"
using namespace std;
using namespace libemb;

/**
 * 迭代器模式：
 * 1.将对聚合对象的访问放到一个类中(迭代器)，从而不用暴露聚合对象的内部表示。
 * 适用场景：
 * 1.遍历容器内的元素
 **/

class Iterator{
DECL_CLASSNAME(Iterator)
public:
    virtual void first()=0;
    virtual void next()=0;
    virtual bool isEnd()=0;
    virtual int currentItem()=0;
};

class Aggregate{
DECL_CLASSNAME(Aggregate)
public:
    virtual Iterator* iterator()=0;
    virtual void push_back(int item)=0;
    virtual int size()=0;
    virtual int getItem(int idx)=0;
};


/* 容器 */
class Container:public Aggregate{
DECL_CLASSNAME(Container)
public:
    Container();
    Iterator* iterator() override;
    void push_back(int item) override;
    int size() override;
    int getItem(int idx) override;
private:
    Iterator* m_iterator;
    int m_items[100]={0};
    int m_count={0};
};

/* 容器迭代器 */
class ContainerIterator:public Iterator{
DECL_CLASSNAME(ContainerIterator)
public:
    ContainerIterator(Aggregate* agg)
    {
        m_agg = agg;
    }
    void first()
    {
        m_idx = 0;
    }
    void next()
    {
        if (m_idx<m_agg->size())
        {
            m_idx++;
        }
    }
    bool isEnd()
    {
        if (m_idx>=m_agg->size())
        {
            return true;
        }
        return false;
    }
    int currentItem()
    {
        return m_agg->getItem(m_idx);
    }
private:
    Aggregate* m_agg;
    int m_idx;
};


Container::Container()
{
    m_iterator = new ContainerIterator(this);
}
Iterator* Container::iterator()
{
    return m_iterator;
}
void Container::push_back(int item)
{
    if (m_count<100)
    {
        m_items[m_count]=item;
        m_count++;
    }
}
int Container::size()
{
    return m_count;
}

int Container::getItem(int idx)
{
    if (idx<m_count)
    {
        return m_items[idx];
    }
    TRACE_ERR_CLASS("out of range!");
    return -1;
}

int main()
{
    Tracer::getInstance().setLevel(TRACE_LEVEL_DBG);
	Tracer::getInstance().addSink(std::make_shared<STDSink>()).start();

    Container container;
    container.push_back(1);
    container.push_back(2);
    container.push_back(3);
    container.push_back(4);

    int i=0;
    //使用迭代器遍历container的所有元素,而不需要借助任何container的方法
    for(auto iter = container.iterator();!iter->isEnd();iter->next())
    {
        TRACE_INFO("container[%d]=%d",i++,iter->currentItem());
    }
    return RC_OK;
}